package tx.core;

import java.awt.Color;
import java.awt.DisplayMode;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.Window;

import tx.core.graphics.NullRepaintManager;
import tx.development.Development;
import tx.screens.GameScreen;
import tx.screens.Screen;
import tx.screens.TitleScreen;
import tx.ui.ScreenManager;

/**
 * The core of the game. The class that provides the game loop.
 * Based on GameCore class, by David Brackeen. 
 * @author Guilherme Mauro Germoglio Barbosa - germoglio@gmail.com
 */
public class GameCore {

	/**
	 * The possible modes for the full screen.
	 */
	private static final DisplayMode[] POSSIBLE_MODES = {
		new DisplayMode(1024, 768, 32, 0),
		new DisplayMode(1024, 768, 24, 0),
		new DisplayMode(1024, 768, 16, 0),
		new DisplayMode(800, 600, 32, 0),
		new DisplayMode(800, 600, 24, 0),
		new DisplayMode(800, 600, 16, 0),
		new DisplayMode(640, 480, 32, 0),
		new DisplayMode(640, 480, 24, 0),
		new DisplayMode(640, 480, 16, 0)
	};

	
	/**
	 * The default font size. 
	 */
	private static final int FONT_SIZE = 24;
	
	
	/**
	 * The ScreenManager.
	 */
	private ScreenManager screenManager;


	private Screen gameScreen;

		
	/**
	 * Calls <code>init()</code> and <code>gameLoop()</code>.
	 */
	public void run() {
		try {
			init();
			gameLoop();
		} finally {
			screenManager.restoreScreen();
		}
	}
	
	/**
	 * Sets full screen mode and initiates objects. 
	 */
	public void init() {
		screenManager = new ScreenManager();
		DisplayMode displayMode = screenManager.findFirstCompatibleMode(POSSIBLE_MODES);
		screenManager.setFullScreen(displayMode);

		NullRepaintManager.install();
		
		Window window = screenManager.getFullScreenWindow();
		window.setFont(new Font("Dialog", Font.PLAIN, FONT_SIZE));
		window.setBackground(Color.black);
		window.setForeground(Color.white);
		
		GameScreen coreGameScreen = new GameScreen(screenManager); 
		
		TitleScreen titleScreen = new TitleScreen(screenManager);
		titleScreen.setGameScreen(coreGameScreen);
		
		coreGameScreen.setTitleScreen(titleScreen);
		
		gameScreen = titleScreen;
		
		gameScreen.init();
		
	}
	
	/**
	 * Runs through game loop until <code>stop()</code> is called.
	 */
	public void gameLoop() {
		long startTime = System.currentTimeMillis();
		long currTime = startTime;
		
		while (gameScreen.isRunning()) {
			long elapsedTime = System.currentTimeMillis() - currTime;
			currTime += elapsedTime;
			
			// update
			update(elapsedTime);
			
			Graphics2D g = screenManager.getGraphics();
			draw(g);
			g.dispose();
			
			screenManager.update();
			
			try {
				Thread.sleep(20);
			} catch (InterruptedException e) {
				if (Development.DEBUG_ENABLED) System.out.println(Development.DEBUG_LABEL + "GameCore.gameLoop() " + e);
			}
			
			gameScreen = gameScreen.nextScreen();
		}
	}
	
	/**
	 * Updates the state of the game/animation based on the amount
	 * of elapsed time that has passed.
	 * @param elapsedTime The elapsed time.
	 */
	public void update(long elapsedTime) {
		this.gameScreen.update(elapsedTime);
	}
	
	/**
	 * Draws to the screen.
	 * @param g The Graphics2D object.
	 */
	public void draw(Graphics2D g) {
		this.gameScreen.draw(g);
	}
}
